home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / cool.lha / ice / pisces / cpp / cpp3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-04  |  12.6 KB  |  492 lines

  1. /*
  2.  *                C P P 3 . C
  3.  *
  4.  *            File open and command line options
  5.  *
  6.  * Edit history
  7.  * 13-Nov-84    MM    Split from cpp1.c
  8.  * 21-Oct-85    rms    Make -g command arg not cause an error.
  9.  * 24-Sep-89    AFM     OS2 and XENIX support.
  10.  * 19-Jan-90    DKM     MVS support.
  11.  * 18-May-90    MBN     Conditional compilation for COOL to get "clean" cpp
  12.  */
  13.  
  14.  
  15. #include    <stdio.h>
  16. #include    <ctype.h>
  17. #include    <time.h>
  18. #include    "cppdef.h"
  19. #include    "cpp.h"
  20.  
  21. /* The type returned from time is double on MVS, long everywhere else.
  22.  * MVS defines this type as time_t.   Add non MVS definition here.
  23.  */
  24. #if HOST != SYS_MVS
  25. #define  time_t long
  26. #endif
  27.  
  28. #if DEBUG && (HOST == SYS_VMS || HOST == SYS_UNIX || HOST == SYS_XENIX || HOST == SYS_OS2 || HOST == SYS_MVS)
  29. #include    <signal.h>
  30. extern int    abort();        /* For debugging        */
  31. #endif
  32.  
  33. extern void expand_line();
  34. extern void expand_file();
  35.  
  36. #ifdef COOL
  37. extern void define_package();       /* Define a new symbol package */
  38. #endif
  39.  
  40. int
  41. openfile(filename)
  42. char        *filename;
  43. /*
  44.  * Open a file, add it to the linked list of open files.
  45.  * This is called only from doinclude().
  46.  */
  47. {
  48.     register FILE        *fp;
  49.  
  50.     if ((fp = fopen(filename, "r")) == NULL) {
  51. #if DEBUG
  52.         perror(filename);
  53. #endif
  54.         return (FALSE);
  55.     }
  56. #if DEBUG
  57.     if (debug)
  58.         fprintf(stderr, "Reading from \"%s\"\n", filename);
  59. #endif
  60.     addfile(fp, filename);
  61.     return (TRUE);
  62. }
  63.  
  64. addfile(fp, filename)
  65. FILE        *fp;            /* Open file pointer        */
  66. char        *filename;        /* Name of the file        */
  67. /*
  68.  * Initialize tables for this open file.  This is called from openfile()
  69.  * above (for #include files), and from the entry to cpp to open the main
  70.  * input file.  It calls a common routine, getfile() to build the FILEINFO
  71.  * structure which is used to read characters.  (getfile() is also called
  72.  * to setup a macro replacement.)
  73.  */
  74. {
  75.     register FILEINFO    *file;
  76.     extern FILEINFO        *getfile();
  77.  
  78.     file = getfile(NBUFF, filename);
  79.     file->fp = fp;            /* Better remember FILE *    */
  80.     file->buffer[0] = EOS;        /* Initialize for first read    */
  81.     line = 1;            /* Working on line 1 now    */
  82.     wrongline = TRUE;        /* Force out initial #line    */
  83. }
  84.  
  85. setincdirs()
  86. /*
  87.  * Append system-specific directories to the include directory list.
  88.  * Called only when cpp is started.
  89.  */
  90. {
  91.  
  92. #ifdef    CPP_INCLUDE
  93.     *incend++ = CPP_INCLUDE;
  94. #define    IS_INCLUDE    1
  95. #else
  96. #define    IS_INCLUDE    0
  97. #endif
  98.  
  99. #if (HOST == SYS_UNIX || HOST == SYS_XENIX)
  100.     *incend++ = "/usr/include";
  101. #define    MAXINCLUDE    (NINCLUDE - 1 - IS_INCLUDE)
  102. #endif
  103.  
  104. #if HOST == SYS_OS2
  105.     *incend++ = "\\ibmc2\\include";
  106. #define    MAXINCLUDE    (NINCLUDE - 1 - IS_INCLUDE)
  107. #endif
  108.  
  109. #if HOST == SYS_MVS
  110. /* MVS will not use the include list via the -I option.  Instead
  111.  * logical ddnames are allocated to a concatenation of include
  112.  * libraries.  Specifying -I for mvs will be an error.
  113.  */
  114. #define    MAXINCLUDE    0
  115. #endif
  116.  
  117. #if HOST == SYS_VMS
  118.     extern char    *getenv();
  119.  
  120.     if (getenv("C$LIBRARY") != NULL)
  121.         *incend++ = "C$LIBRARY:";
  122.     *incend++ = "SYS$LIBRARY:";
  123. #define    MAXINCLUDE    (NINCLUDE - 2 - IS_INCLUDE)
  124. #endif
  125.  
  126. #if HOST == SYS_RSX
  127.     extern int    $$rsts;            /* TRUE on RSTS/E    */
  128.     extern int    $$pos;            /* TRUE on PRO-350 P/OS    */
  129.     extern int    $$vms;            /* TRUE on VMS compat.    */
  130.  
  131.     if ($$pos) {                /* P/OS?        */
  132.         *incend++ = "SY:[ZZDECUSC]";    /* C #includes        */
  133.         *incend++ = "LB:[1,5]";        /* RSX library        */
  134.     }
  135.     else if ($$rsts) {            /* RSTS/E?        */
  136.         *incend++ = "SY:@";            /* User-defined account    */
  137.         *incend++ = "C:";            /* Decus-C library    */
  138.         *incend++ = "LB:[1,1]";        /* RSX library        */
  139.     }
  140.     else if ($$vms) {            /* VMS compatibility?    */
  141.         *incend++ = "C:";
  142.     }
  143.     else {                    /* Plain old RSX/IAS    */
  144.         *incend++ = "LB:[1,1]";
  145.     }
  146. #define    MAXINCLUDE    (NINCLUDE - 3 - IS_INCLUDE)
  147. #endif
  148.  
  149. #if HOST == SYS_RT11
  150.     extern int    $$rsts;            /* RSTS/E emulation?    */
  151.  
  152.     if ($$rsts)
  153.         *incend++ = "SY:@";            /* User-defined account    */
  154.     *incend++ = "C:";            /* Decus-C library disk    */
  155.     *incend++ = "SY:";            /* System (boot) disk    */
  156. #define    MAXINCLUDE    (NINCLUDE - 3 - IS_INCLUDE)
  157. #endif
  158. }
  159.  
  160. int
  161. dooptions(argc, argv)
  162. int        argc;
  163. char        *argv[];
  164. /*
  165.  * dooptions is called to process command line arguments (-Detc).
  166.  * It is called only at cpp startup.
  167.  */
  168. {
  169.     register char        *ap;
  170.     register DEFBUF        *dp;
  171.     register int        c;
  172.     int            i, j;
  173.     char            *arg;
  174.     SIZES            *sizp;        /* For -S        */
  175.     int            size;        /* For -S        */
  176.     int            isdatum;    /* FALSE for -S*    */
  177.     int            endtest;    /* For -S        */
  178.  
  179.     for (i = j = 1; i < argc; i++) {
  180.         arg = ap = argv[i];
  181.         if (*ap++ != '-' || *ap == EOS)
  182.         argv[j++] = argv[i];
  183.         else {
  184.         c = *ap++;            /* Option byte        */
  185.         if (islower(c))            /* Normalize case    */
  186.             c = toupper(c);
  187.         switch (c) {            /* Command character    */
  188.         case 'C':            /* Keep comments    */
  189.             cflag = TRUE;
  190.             keepcomments = TRUE;
  191.             break;
  192.  
  193.         case 'D':            /* Define symbol    */
  194. #if (HOST != SYS_UNIX && HOST != SYS_XENIX && HOST != SYS_OS2 && HOST != SYS_MVS)
  195.             zap_uc(ap);            /* Force define to U.C.    */
  196. #endif
  197.             /*
  198.              * If the option is just "-Dfoo", make it -Dfoo=1
  199.              */
  200.             while (*ap != EOS && *ap != '=')
  201.             ap++;
  202.             if (*ap == EOS)
  203.             ap = "1";
  204.             else
  205.             *ap++ = EOS;
  206.             /*
  207.              * Now, save the word and its definition.
  208.              */
  209.             dp = defendel(argv[i] + 2, FALSE);
  210.             dp->repl = savestring(ap);
  211.             dp->nargs = DEF_NOARGS;
  212.             break;
  213.  
  214.         case 'E':            /* Ignore non-fatal    */
  215.             eflag = TRUE;        /* errors.        */
  216.             break;
  217.  
  218.         case 'G':            /* Cmpiler's debug switch */
  219.             break;
  220.  
  221.         case 'B':            /* Sun's ignore // comments */
  222.             break;
  223.  
  224.         case 'I':            /* Include directory    */
  225.             if (incend >= &incdir[MAXINCLUDE])
  226.             cfatal("Too many include directories", NULLST);
  227.             *incend++ = ap;
  228.             break;
  229.  
  230.         case 'N':            /* No predefineds    */
  231.             nflag++;            /* Repeat to undefine    */
  232.             break;            /* __LINE__, etc.    */
  233.  
  234.         case 'S':
  235.             sizp = size_table;
  236.             if (isdatum = (*ap != '*'))    /* If it's just -S,    */
  237.             endtest = T_FPTR;    /* Stop here        */
  238.             else {            /* But if it's -S*    */
  239.             ap++;            /* Step over '*'    */
  240.             endtest = 0;        /* Stop at end marker    */
  241.             }
  242.             while (sizp->bits != endtest && *ap != EOS) {
  243.             if (!isdigit(*ap)) {    /* Skip to next digit    */
  244.                 ap++;
  245.                 continue;
  246.             }
  247.             size = 0;        /* Compile the value    */
  248.             while (isdigit(*ap)) {
  249.                 size *= 10;
  250.                 size += (*ap++ - '0');
  251.             }
  252.             if (isdatum)
  253.                 sizp->size = size;    /* Datum size        */
  254.             else
  255.                 sizp->psize = size;    /* Pointer size        */
  256.             sizp++;
  257.             }
  258.             if (sizp->bits != endtest)
  259.             cwarn("-S, too few values specified in %s", argv[i]);
  260.             else if (*ap != EOS)
  261.             cwarn("-S, too many values, \"%s\" unused", ap);
  262.             break;
  263.  
  264.         case 'U':            /* Undefine symbol    */
  265. #if (HOST != SYS_UNIX && HOST != SYS_XENIX && HOST != SYS_OS2 && HOST != SYS_MVS)
  266.             zap_uc(ap);
  267. #endif
  268.             if (defendel(ap, TRUE) == NULL)
  269.             cwarn("\"%s\" wasn't defined", ap);
  270.             break;
  271.  
  272.         case 'X':            /* Debug        */
  273.             debug = (isdigit(*ap)) ? atoi(ap) : 1;
  274. #if DEBUG
  275. #if (HOST == SYS_VMS || HOST == SYS_UNIX || HOST == SYS_XENIX || HOST == SYS_OS2)
  276.             signal(SIGINT, abort);    /* Trap "interrupt"    */
  277. #endif
  278. #endif
  279.             fprintf(stderr, "Debug set to %d\n", debug);
  280.             break;
  281.  
  282.         default:            /* What is this one?    */
  283.             cwarn("Unknown option \"%s\"", arg);
  284.             fprintf(stderr, "The following options are valid:\n\
  285.   -C\t\t\tWrite source file comments to output\n\
  286.   -Dsymbol=value\tDefine a symbol with the given (optional) value\n\
  287.   -Idirectory\t\tAdd a directory to the #include search list\n\
  288.   -N\t\t\tDon't predefine target-specific names\n\
  289.   -Stext\t\tSpecify sizes for #if sizeof\n\
  290.   -Usymbol\t\tUndefine symbol\n\
  291.   -Xvalue\t\tSet internal debug flag\n");
  292.             break;
  293.         }            /* Switch on all options    */
  294.         }                /* If it's a -option        */
  295.     }                /* For all arguments        */
  296.     if (j > 3) {
  297.         cerror(
  298.         "Too many file arguments.  Usage: cpp [input [output]]",
  299.         NULLST);
  300.     }
  301.     return (j);            /* Return new argc        */
  302. }
  303.  
  304. #if (HOST != SYS_UNIX && HOST != SYS_XENIX && HOST != SYS_OS2 && HOST != SYS_MVS)
  305. FILE_LOCAL
  306. zap_uc(ap)
  307. register char    *ap;
  308. /*
  309.  * Dec operating systems mangle upper-lower case in command lines.
  310.  * This routine forces the -D and -U arguments to uppercase.
  311.  * It is called only on cpp startup by dooptions().
  312.  */
  313. {
  314.     while (*ap != EOS) {
  315.         /*
  316.          * Don't use islower() here so it works with Multinational
  317.          */
  318.         if (*ap >= 'a' && *ap <= 'z')
  319.         *ap = toupper(*ap);
  320.         ap++;
  321.     }
  322. }
  323. #endif
  324.  
  325. define_builtin (name, function, replacement)
  326.      char *name;
  327.      void (*function)();
  328.      char *replacement;
  329. {
  330.   DEFBUF *dp;
  331.   dp = defendel(name, FALSE);
  332.   dp->repl = replacement;
  333.   dp->expander = function;
  334.   dp->nargs = (function == NULL) ? DEF_NOARGS : DEF_BUILTIN;
  335. }
  336.  
  337. static char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  338.                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",};
  339.  
  340. initdefines()
  341. /*
  342.  * Initialize the built-in #define's.  There are two flavors:
  343.  *     #xomdefine decus    1        (static definitions)
  344.  *    #define    __FILE__ ??        (dynamic, evaluated by magic)
  345.  * Called only on cpp startup.
  346.  *
  347.  * Note: the built-in static definitions are supressed by the -N option.
  348.  * __LINE__, __FILE__, and __DATE__ are always present.
  349.  */
  350. {
  351.     register char        **pp;
  352.     register char        *tp;
  353.     register DEFBUF        *dp;
  354.     struct tm        *tvec;
  355.     /*
  356.      * Predefine the built-in symbols.  Allow the
  357.      * implementor to pre-define a symbol as "" to
  358.      * eliminate it.
  359.      */
  360.     if (nflag == 0) {
  361.         for (pp = preset; *pp != NULL; pp++) {
  362.         if (*pp[0] != EOS) {
  363.             dp = defendel(*pp, FALSE);
  364.             dp->repl = savestring("1");
  365.             dp->nargs = DEF_NOARGS;
  366.         }
  367.         }
  368.     }
  369.  
  370.     if (nflag < 2) {
  371.  
  372.       define_builtin("__LINE__", expand_line, "");
  373.       define_builtin("__FILE__", expand_file, "");
  374.       define_builtin("__STDC__", NULL, "1");
  375. #if OK_DATE
  376.       /*
  377.        * Define __DATE__ as today's date.
  378.        */
  379.       { time_t clock = time(NULL);
  380.         tvec = localtime(&clock);}
  381.       tp = getmem(12);
  382.       /* strftime(tp, 12, "%b %d %Y", tp); */
  383.       sprintf(tp, "%s %02d %04d",
  384.           months[tvec->tm_mon],
  385.           tvec->tm_mday,
  386.           tvec->tm_year + 1900);
  387.       define_builtin( "__DATE__", NULL, tp);
  388.  
  389.       tp = getmem(9);
  390.       /* strftime(tp, 9, "%H:%M:%S", tp); */
  391.       sprintf(tp, "%02d:%02d:%02d",
  392.           tvec->tm_hour,
  393.           tvec->tm_min,
  394.           tvec->tm_sec);
  395.       define_builtin( "__TIME__", NULL, tp);
  396. #endif
  397. #ifdef COOL
  398.       define_builtin("DEFPACKAGE", define_package, "");
  399. #endif
  400.     }
  401. }
  402.  
  403. #if HOST == SYS_VMS
  404. /*
  405.  * getredirection() is intended to aid in porting C programs
  406.  * to VMS (Vax-11 C) which does not support '>' and '<'
  407.  * I/O redirection.  With suitable modification, it may
  408.  * useful for other portability problems as well.
  409.  */
  410.  
  411. int
  412. getredirection(argc, argv)
  413. int        argc;
  414. char        **argv;
  415. /*
  416.  * Process vms redirection arg's.  Exit if any error is seen.
  417.  * If getredirection() processes an argument, it is erased
  418.  * from the vector.  getredirection() returns a new argc value.
  419.  *
  420.  * Warning: do not try to simplify the code for vms.  The code
  421.  * presupposes that getredirection() is called before any data is
  422.  * read from stdin or written to stdout.
  423.  *
  424.  * Normal usage is as follows:
  425.  *
  426.  *    main(argc, argv)
  427.  *    int        argc;
  428.  *    char        *argv[];
  429.  *    {
  430.  *        argc = getredirection(argc, argv);
  431.  *    }
  432.  */
  433. {
  434.     register char        *ap;    /* Argument pointer    */
  435.     int            i;    /* argv[] index        */
  436.     int            j;    /* Output index        */
  437.     int            file;    /* File_descriptor     */
  438.     extern int        errno;    /* Last vms i/o error     */
  439.  
  440.     for (j = i = 1; i < argc; i++) {   /* Do all arguments    */
  441.         switch (*(ap = argv[i])) {
  442.         case '<':            /* <file        */
  443.         if (freopen(++ap, "r", stdin) == NULL) {
  444.             perror(ap);        /* Can't find file    */
  445.             exit(errno);    /* Is a fatal error    */
  446.         }
  447.         break;
  448.  
  449.         case '>':            /* >file or >>file    */
  450.         if (*++ap == '>') {    /* >>file        */
  451.             /*
  452.              * If the file exists, and is writable by us,
  453.              * call freopen to append to the file (using the
  454.              * file's current attributes).  Otherwise, create
  455.              * a new file with "vanilla" attributes as if the
  456.              * argument was given as ">filename".
  457.              * access(name, 2) returns zero if we can write on
  458.              * the specified file.
  459.              */
  460.             if (access(++ap, 2) == 0) {
  461.             if (freopen(ap, "a", stdout) != NULL)
  462.                 break;    /* Exit case statement    */
  463.             perror(ap);    /* Error, can't append    */
  464.             exit(errno);    /* After access test    */
  465.             }            /* If file accessable    */
  466.         }
  467.         /*
  468.          * On vms, we want to create the file using "standard"
  469.          * record attributes.  creat(...) creates the file
  470.          * using the caller's default protection mask and
  471.          * "variable length, implied carriage return"
  472.          * attributes. dup2() associates the file with stdout.
  473.          */
  474.         if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1
  475.          || dup2(file, fileno(stdout)) == -1) {
  476.             perror(ap);        /* Can't create file    */
  477.             exit(errno);    /* is a fatal error    */
  478.         }            /* If '>' creation    */
  479.         break;            /* Exit case test    */
  480.  
  481.         default:
  482.         argv[j++] = ap;        /* Not a redirector    */
  483.         break;            /* Exit case test    */
  484.         }
  485.     }                /* For all arguments    */
  486.     argv[j] = NULL;            /* Terminate argv[]    */
  487.     return (j);            /* Return new argc    */
  488. }
  489. #endif
  490.  
  491.  
  492.